#include "AssimpLoader.h"

#include "D3D11.h"
#include "xnamath.h"
#include "StringUtils.h"

#include <string>
#include <vector>

#include "LWOFile.h"

typedef std::vector<Vertex> VertexVec;
typedef std::vector<DWORD> IndexVec;
typedef std::vector<XMFLOAT3> TexCoordsVec;
typedef std::vector<int> IntVec;
typedef std::vector<SubsetData> SubsetDataVec;

AssimpLoader::AssimpLoader()
{
	mLWOFileLoader = new LWOFile;
}

AssimpLoader::~AssimpLoader()
{
	delete mLWOFileLoader;
}

void CreateMeshData(const VertexVec *pVertices, const IndexVec *pIndices, const SubsetDataVec *pSubsets, MeshData* pOutMeshData)
{
	pOutMeshData->mVertexCount = (DWORD)pVertices->size();
	pOutMeshData->mpVertices = new Vertex[pOutMeshData->mVertexCount];
	for(DWORD i = 0; i < pOutMeshData->mVertexCount; i++)
	{
		pOutMeshData->mpVertices[i] = (*pVertices)[i];
	}

	pOutMeshData->mIndexCount = (DWORD)pIndices->size();
	pOutMeshData->mpIndices = new DWORD[pOutMeshData->mIndexCount];
	for(DWORD i = 0; i < pOutMeshData->mIndexCount; i++)
	{
		pOutMeshData->mpIndices[i] = (*pIndices)[i];
	}

	pOutMeshData->mSubsetCount = (DWORD)pSubsets->size();
	pOutMeshData->mpSubsets = new SubsetData[pOutMeshData->mSubsetCount];
	for(DWORD i = 0; i < pOutMeshData->mSubsetCount; i++)
	{
		pOutMeshData->mpSubsets[i] = (*pSubsets)[i];
	}
}

bool AssimpLoader::LoadFromFile(const char* filePath, MeshData** output)
{
	// try to load
	if(!mLWOFileLoader->LoadFromFile(filePath))
	{
		// failed, print all errors
		std::string strErrors = "Loading LWO failed:\n";
		std::list<std::string>::iterator it;
		for(it = mLWOFileLoader->m_Errors.begin(); it != mLWOFileLoader->m_Errors.end(); ++it) strErrors += (*it)+"\n";
		strErrors += "\nIf you launched the demo from Visual Studio, set the 'Working Directory' in project settings correctly.";
		MessageBoxA(NULL,strErrors.c_str(),"Error!",MB_OK);
		return false;
	}

	MeshData* &outMesh = *output;
	outMesh = new MeshData();

	VertexVec vertices;
	IndexVec indices;
	SubsetDataVec subsets;
	XMMATRIX indentity = XMMatrixIdentity();


	// calculate normals
	mLWOFileLoader->CalculateNormals();

	// get first layer only
	LWOFile::Layer *pLayer = mLWOFileLoader->m_Layers[0];

	// make vertex buffer
	//
	// 9 floats per vertex (3 pos, 3 norm, 3 color)
	Vertex vtx;
	for(unsigned int i = 0; i < pLayer->m_iPoints; i++)
	{
		vtx.mPosition = XMFLOAT3(pLayer->m_Points[i*3+0], pLayer->m_Points[i*3+1], pLayer->m_Points[i*3+2]);
		vtx.mNormal = XMFLOAT3(pLayer->m_Points[i*3+0], pLayer->m_Points[i*3+1], pLayer->m_Points[i*3+2]);
		vtx.mTangent = XMFLOAT3(1.0f, 0.0f, 0.0f);
		vtx.mTexC = XMFLOAT2(0.0f, 0.0f);

		vertices.push_back(vtx);
	}

	// make index buffer
	//
	for(unsigned int i = 0; i < pLayer->m_Polygons.size(); i++)
	{
		const LWOFile::Polygon &poly = pLayer->m_Polygons[i];

		// skip non-triangles
		if(poly.m_Vertices.size() != 3) continue;

		indices.push_back(poly.m_Vertices[0]);
		indices.push_back(poly.m_Vertices[1]);
		indices.push_back(poly.m_Vertices[2]);
	}

	// make subset
	SubsetData sbData;
	sbData.mStartIndex = 0;
	sbData.mTriangleCount = (DWORD)(indices.size() / 3);
	sbData.mWorld = XMFLOAT4X4(1.0f, 0.0f, 0.0f, 0.0f,
		                       0.0f, 1.0f, 0.0f, 0.0f,
							   0.0f, 0.0f, 1.0f, 0.0f,
							   0.0f, 0.0f, 0.0f, 1.0f);
	sbData.mDiffuse = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
	sbData.mSpecular = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
	sbData.mAmbient = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
	sbData.mEmission = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
	sbData.mShininess = 5.0f;
	sbData.mDiffuseMapFilePath = "";
	sbData.mNormalMapFilePath = "";
	subsets.push_back(sbData);

	CreateMeshData(&vertices, &indices, &subsets, outMesh);
	

	return true;
}
// 
// bool AssimpLoader::LoadFromFile(const char* filePath, MeshData** output)
// {
// 	bool res;
// 
// 	std::string folder;
// 	StringUtils::ExctractFolder(&std::string(filePath), &folder);
// 
// 	Assimp::Importer importer;
// 
// 	const aiScene* pScene = importer.ReadFile(filePath, 0
// 		| aiProcessPreset_TargetRealtime_Quality 
// 		| aiProcess_ConvertToLeftHanded
// 		| aiProcess_PreTransformVertices
// 		);
// 
// 
// 	if (pScene != NULL)
// 	{
// 		MeshData* &outMesh = *output;
// 		outMesh = new MeshData();
// 
// 		VertexVec vertices;
// 		IndexVec indices;
// 
// 		IntVec verticesStartOffsets;
// 		IntVec indicesStartOffsets;
// 
// 		XMMATRIX indentity = XMMatrixIdentity();
// 
// 		SubsetDataVec subsets;
// 
// 		AcquireVerticesData(pScene, &vertices, &verticesStartOffsets);
// 		AcquireIndicesData(pScene, &verticesStartOffsets, &indices, &indicesStartOffsets);
// 
// 		AcquireSubsetsData(pScene, pScene->mRootNode, &indentity, &indicesStartOffsets, &folder, &subsets);
// 
// 		CreateMeshData(&vertices, &indices, &subsets, outMesh);
// 
// 		res = true;
// 	}
// 	else
// 	{
// 		res = false;
// 	}
// 
// 	return res;
// }
